package com.dss.auto_deploy.util;

import com.dss.auto_deploy.config.WebsocketEndPoint;
import com.dss.auto_deploy.domain.Deploy;
import com.dss.auto_deploy.dto.WsSendDto;
import com.dss.auto_deploy.mapper.IDeployMapper;
import com.jcraft.jsch.SftpProgressMonitor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.text.DecimalFormat;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @Description: 上传进度监控
 * @author: dongshoushan
 */
@Component
@Slf4j
public class FileProgressMonitor implements SftpProgressMonitor {
    /**
     * 默认间隔时间为2秒
     */
    private static final long progressInterval = 2;
    /**
     * 记录传输是否结束
     */
    private boolean isEnd = false;
    /**
     * 记录已传输的数据总大小
     */
    private long transfered;
    private Long id;
    /**
     * ip
     */
    private String ip;
    /**
     * 项目名称
     */
    private String projectName;
    /**
     * 记录文件总大小
     */
    private long fileSize;
    private String table;
    /**
     * 记录是否已启动记时器
     */
    private boolean isScheduled = false;
    private long start;
    private static ScheduledThreadPoolExecutor scheduledThreadPoolExecutor;
    private ScheduledFuture schedule;
    private static IDeployMapper deployMapper;

    public static void setDeployMapper(IDeployMapper deployMapper) {
        FileProgressMonitor.deployMapper = deployMapper;
    }

    public static void setScheduledThreadPoolExecutor(ScheduledThreadPoolExecutor scheduledThreadPoolExecutor) {
        FileProgressMonitor.scheduledThreadPoolExecutor = scheduledThreadPoolExecutor;
    }


    public static WebsocketEndPoint websocketEndPoint;

    public static void setWebsocketEndPoint(WebsocketEndPoint websocketEndPoint) {
        FileProgressMonitor.websocketEndPoint = websocketEndPoint;
    }

    public FileProgressMonitor() {
    }

    public FileProgressMonitor(Long id, String ip, String name, String table) {
        this.id = id;
        this.ip = ip;
        this.projectName = name;
        this.table = table;
    }

    public void stop() {
        //任务关闭
        schedule.cancel(true);
        isScheduled = false;
        start = 0;
    }

    public void start() {
        System.out.println("开始上传。。。。");
        start = System.currentTimeMillis();
        isScheduled = true;
        schedule = scheduledThreadPoolExecutor.scheduleAtFixedRate(() -> {
            try {
                if (!isEnd()) { // 判断传输是否已结束
                    long transfered = getTransfered();
                    sendProgressMessage(transfered);
                    if (transfered == fileSize) { // 判断当前已传输数据大小是否等于文件总大小
                        setEnd(true); // 如果当前已传输数据大小等于文件总大小，说明已完成，设置end
                    }
                } else {
                    sendProgressMessage(fileSize);
                    stop(); // 如果传输结束，停止记时器
                }
            }catch (Exception e){
                e.printStackTrace();
            }

        }, 0, progressInterval, TimeUnit.SECONDS);

    }

    /**
     * 打印progress信息
     *
     * @param transfered
     */
    private void sendProgressMessage(long transfered) {
        if (fileSize != 0) {
            String transferedValue = StringUtils.computerUnitConversion(transfered);
            float d = ((float) transfered * 100) / (float) fileSize;
            DecimalFormat df = new DecimalFormat("#.##");
            String speedOfProgress = df.format(d) + "%";
            float speed = ((float) transfered * 1000) / (float) (System.currentTimeMillis() - start);
            String speedValue = StringUtils.computerUnitConversionSpeed(speed);
            //上传进度推送
            websocketEndPoint.send(WsSendDto.builder().type(0).table(table).status("uploading")
                    .speed(speedValue).transfered(transferedValue).fileSize(StringUtils.computerUnitConversion(fileSize))
                    .speedOfProgress(speedOfProgress).ip(ip).name(projectName).id(Long.valueOf(id))
                    .build());
            Deploy deploy = deployMapper.selectById(id);
            deploy.setFileSize(StringUtils.computerUnitConversion(fileSize));
            deploy.setSpeedOfProgress(speedOfProgress);
            deploy.setSpeed(speedValue);
            deploy.setTransfered(transferedValue);
            deployMapper.updateById(deploy);
        } else {
            System.out.println("Sending progress message: " + transfered);
        }

    }

    /**
     * 实现了SftpProgressMonitor接口的count方法
     */
    @Override
    public boolean count(long count) {
        if (isEnd()) {
            return false;
        }
        if (!isScheduled) {
            start();
        }
        add(count);
        return true;
    }

    /**
     * 实现了SftpProgressMonitor接口的end方法
     */
    @Override
    public void end() {
        setEnd(true);
    }

    private synchronized void add(long count) {
        transfered = transfered + count;
    }

    private synchronized long getTransfered() {
        return transfered;
    }

    public synchronized void setTransfered(long transfered) {
        this.transfered = transfered;
    }

    private synchronized void setEnd(boolean isEnd) {
        this.isEnd = isEnd;
    }

    private synchronized boolean isEnd() {
        return isEnd;
    }

    @Override
    public void init(int op, String src, String dest, long max) {
        // Not used for putting InputStream
        String s = StringUtils.format("init {} {} {} {}", op, src, dest, max);
        this.fileSize = max;
    }
}
